home *** CD-ROM | disk | FTP | other *** search
Wrap
Newsgroups: comp.sys.atari.st.tech Path: news.cis.umn.edu!umn.edu!The-Star.honeywell.com!sol.ctr.columbia.edu!zaphod.mps.ohio-state.edu!wupost!uunet!mnemosyne.cs.du.edu!nyx!ilepore From: ilepore@nyx.cs.du.edu (Ian Lepore) Subject: Re: Passing modified environment to child process--HOW? Message-ID: <1992Jul16.070022.21116@mnemosyne.cs.du.edu> X-Disclaimer: Nyx is a public access Unix system run by the University of Denver for the Denver community. The University has neither control over nor responsibility for the opinions of users. Sender: usenet@mnemosyne.cs.du.edu (netnews admin account) Reply-To: ilepore@nyx.UUCP (Ian Lepore) Organization: Nyx, Public Access Unix at U. of Denver Math/CS dept. References: <75723@ut-emx.uucp> Date: Thu, 16 Jul 92 07:00:22 GMT Lines: 217 I got a couple email requests to post the code for passing environ[] vars via Pexec(), so here it is... Note that this also passes args via the Atari ARGV standard. --------- cut here ---------------------------------------------------- /* SPAWN.C */ #include <stdlib.h> #include <errno.h> #include <osbind.h> static char *nullenv[] = {NULL}; /*------------------------------------------------------------------------ * Return the total length of the characters and null terminators in * an array of pointers to strings terminated by a NULL pointer. *------------------------------------------------------------------------ static unsigned e_strlen(strings) register char **strings; { register char *pstring; register unsigned length = 0; while (*strings) { length += 1 + strlen(*strings++); /* +1 for nullterm char */ } return length; } /*------------------------------------------------------------------------ * Copy a string, including the null terminator, and return a pointer * to the end of the destination string. *------------------------------------------------------------------------ static char *str0cpy(dest, source) register char *dest; register char *source; { while (*dest++ = *source++) continue; return dest; } /*------------------------------------------------------------------------ * Copy an array of strings into an environment string, and return a point * to the end of the environment string. *------------------------------------------------------------------------ static char *e_strcpy(envstring, strings) register char *envstring; register char **strings; { while( *strings != 0 ) { envstring = str0cpy( envstring, *strings ); ++strings; } return envstring; /* Return end of environment string */ } /*------------------------------------------------------------------------ * Run a program, passing it arguments according to the ARGV spec. *------------------------------------------------------------------------ int _Execve(childname, args, envv) char *childname; char **args; char **envv; { register unsigned envsize; long rv; register char *penvargs; register char *ptail; char *childenv; register char *pchildenv; register unsigned lentail; register char argch,; char tail[128]; static char argvar[] = "ARGV="; /* * Find out how much memory we'll need for the child's environment */ if (NULL == envv) { /* use global environ if specific * if (NULL == (envv = environ)) /* environ wasn't given; if global* envv = nullenv; /* env is not valid, use dummy. * } envsize = e_strlen(envv); /* length of environment envsize += e_strlen(args); /* plus command tail args envsize += 1 + strlen(childname); /* plus length of argv[0] envsize += 7; /* plus length of ARGV= var envsize += envsize & 1; /* padded to even # of bytes. /* * Allocate and fill in the child's environment */ childenv = (char *)(rv = Malloc(envsize)); if( rv < 0 ) { return rv; /* Malloc error */ } pchildenv = e_strcpy(childenv, envv); /* copy caller environment pchildenv = str0cpy(pchildenv, argvar); /* append ARGV variable pchildenv = str0cpy(pchildenv, args[0]); /* copy argv[0] penvargs = pchildenv; /* save start of args pchildenv = e_strcpy(pchildenv, &args[1]); /* append rest of argv[] *pchildenv = 0; /* terminate environment /* put as much in the command tail as will fit */ lentail = 0; ptail = &tail[1]; while(lentail < 125 && penvargs < pchildenv) { ++lentail; argch = *penvargs++; if( argch == 0 ) { *ptail++ = ' '; } else { *ptail++ = argch; } } while (lentail < 126) { /* pad remainder of command tail with nulls */ ++lentail; *ptail++ = '\0'; } tail[0] = 127; /* indicate valid ARGV present */ /* * Execute child, returning program status or error */ rv = Pexec(0, childname, tail, childenv); Mfree(childenv); if (rv < 0L) { errno = rv; return ERROR; } else { return rv; } } /*------------------------------------------------------------------------ * count the number of pointers in an argv[] array. *------------------------------------------------------------------------ static int count_argv(argv) register char **argv; { register int counter = -1; for (;;) { ++counter; if (*argv++ == NULL) { return counter; } } } /*------------------------------------------------------------------------ * the spawn-family functions... * (macros in process.h map these things to their proper names) *------------------------------------------------------------------------ int _Spv(mode, childname, argv) int mode; char *childname; char **argv; { return _Execve(childname, argv, NULL); } int _Spve(mode, childname, argv, envv) int mode; char *childname; char **argv; char **envv; { return _Execve(childname, argv, envv); } int _Spl(mode, childname, arg0) int mode; char *childname; char *arg0; { return _Spv(mode, childname, &arg0); } int _Sple(mode, childname, arg0) int mode; char *childname; char *arg0; { register char **argv; register void *envp; register int argc; argv = &arg0; argc = count_argv(argv); envp = &argv[argc+1]; return _Spve(mode, childname, argv, envp); } --------------- cut here ------------------------------ -- - Ian (void *) where prohibited by law